package com.sh.fmbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sh.fmbackend.common.ErrorCode;
import com.sh.fmbackend.exception.BusinessException;
import com.sh.fmbackend.mapper.TeamMapper;
import com.sh.fmbackend.mapper.UserTeamMapper;
import com.sh.fmbackend.model.domain.Team;
import com.sh.fmbackend.model.domain.User;
import com.sh.fmbackend.model.domain.UserTeam;
import com.sh.fmbackend.model.dto.TeamQuery;
import com.sh.fmbackend.model.enums.TeamStatusEnum;
import com.sh.fmbackend.model.request.TeamJoinRequest;
import com.sh.fmbackend.model.request.TeamQuitRequest;
import com.sh.fmbackend.model.request.TeamUpdateRequest;
import com.sh.fmbackend.model.vo.TeamUserVO;
import com.sh.fmbackend.model.vo.UserVO;
import com.sh.fmbackend.service.TeamService;
import com.sh.fmbackend.service.UserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 舒云
 * @description 针对表【team(队伍)】的数据库操作Service实现
 * @createDate 2024-12-30 21:20:57
 */
@Service
public class TeamServiceImpl extends ServiceImpl<TeamMapper, Team>
        implements TeamService {

    @Resource
    private UserTeamServiceImpl userTeamService;

    @Resource
    private UserService userService;
    @Resource
    private TeamMapper teamMapper;
    @Resource
    private UserTeamMapper userTeamMapper;

    /**
     * @param team
     * @param loginUser
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public long addTeam(Team team, User loginUser) {
        if (team == null || loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求数据为空");
        }
        //  a. 队伍人数 > 1 且 <= 20
        Integer maxNum = team.getMaxNum();
        if (maxNum == null || maxNum < 1 || maxNum > 20) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数不合法");
        }
        //  b. 队伍标题 <= 20
        String name = team.getName();
        if (name == null || name.length() > 20 || StringUtils.isBlank(name)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍标题不合法");
        }
        //  c. 描述 <= 512
        String description = team.getDescription();
        if (description == null || description.length() > 512) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍描述不合法");
        }
        //  d. status 是否公开（int）不传默认为 0（公开）
        int status = Optional.ofNullable(team.getStatus()).orElse(0);
        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(status);
        if (statusEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍状态不合法");
        }
        if (TeamStatusEnum.SECRET.equals(statusEnum) && (team.getPassword() == null || team.getPassword().length() > 32)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍密码不合法");
        }
        //  e. 超时时间 在 当前时间 前
        Date expireTime = team.getExpireTime();
        if (expireTime == null || expireTime.before(new Date())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍超时时间不合法");
        }
        //  f. 校验用户最多创建 5 个队伍
        // todo 可能同时创建100个队伍，如何处理？
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", loginUser.getId());
        long hasTeamNum = this.count(queryWrapper);
        if (hasTeamNum >= 5) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多创建 5 个队伍");
        }
//     * 4. 插入队伍信息到队伍表
        team.setId(null);
        team.setUserId(loginUser.getId());
        boolean res = this.save(team);
        Long teamId = team.getId();  // 生成的主键Id
        if (!res || teamId == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建队伍失败");
        }
//     * 5. 插入用户  => 队伍关系到关系表
        UserTeam userTeam = new UserTeam();
        userTeam.setTeamId(team.getId());
        userTeam.setUserId(loginUser.getId());
        userTeam.setJoinTime(new Date());
        res = userTeamService.save(userTeam);
        if (!res) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "创建队伍失败");
        }
        return teamId;
    }

    @Override
    public List<TeamUserVO> listTeams(TeamQuery teamQuery, boolean isAdmin) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if (teamQuery != null) {
            Long id = teamQuery.getId();
            // id
            if (id != null && id > 0) {
                queryWrapper.or().eq("id", id);
            }
            if (CollectionUtils.isNotEmpty(teamQuery.getIdList())) {
                queryWrapper.in("id", teamQuery.getIdList());
            }
            // 模糊搜索
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)) {
                queryWrapper.or().like("name", searchText);
                queryWrapper.or().like("description", searchText);
            }
            // 精确名字搜索
            String name = teamQuery.getName();
            if (StringUtils.isNotBlank(name)) {
                queryWrapper.or().like("name", name);
            }
            // 精确描述搜索
            String description = teamQuery.getDescription();
            if (StringUtils.isNotBlank(description)) {
                queryWrapper.or().like("description", description);
            }
            // 精确最大人数搜索
            Integer maxNum = teamQuery.getMaxNum();
            if (maxNum != null && maxNum > 0) {
                queryWrapper.or().eq("maxNum", maxNum);
            }
            // 精确队长ID搜索
            Long userId = teamQuery.getUserId();
            if (userId != null && userId > 0) {
                queryWrapper.or().eq("userId", userId);
            }
            // 精确状态搜索
            Integer status = teamQuery.getStatus();
            TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(status);
            if (statusEnum == null) {
                statusEnum = TeamStatusEnum.PUBLIC;
            }
            if (!isAdmin && !statusEnum.equals(TeamStatusEnum.PUBLIC)) {
                throw new BusinessException(ErrorCode.NO_AUTH, "无权限查看非公开队伍");
            }
            if (status != null && status > -1) {
                queryWrapper.or().eq("status", statusEnum.getValue());
            }
        }
        queryWrapper.or().gt("expireTime", new Date()).or().isNull("expireTime");
        // 所有符合条件的队伍
        List<Team> teamList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(teamList)) {
            return new ArrayList<>();
        }
        // 信息
        List<TeamUserVO> teamUserVOS = new ArrayList<>();
        for (Team team : teamList) {
            Long userId = team.getUserId();  // 队长ID
            User user = userService.getById(userId);

            TeamUserVO teamUserVO = new TeamUserVO();
            BeanUtils.copyProperties(team, teamUserVO);

            if (user != null) {
                UserVO userVO = new UserVO();
                BeanUtils.copyProperties(user, userVO);
                teamUserVO.setCreateUser(userVO);
            }
            teamUserVOS.add(teamUserVO);
        }
        return teamUserVOS;
    }


    @Override
    public List<TeamUserVO> listTeamsStrong(TeamQuery teamQuery, HttpServletRequest request) {
        QueryWrapper<Team> queryWrapper = new QueryWrapper<>();
        if (teamQuery != null) {
            Long id = teamQuery.getId();
            // id
            if (id != null && id > 0) {
                queryWrapper.or().eq("id", id);
            }
            if (CollectionUtils.isNotEmpty(teamQuery.getIdList())) {
                queryWrapper.in("id", teamQuery.getIdList());
            }
            // 模糊搜索
            String searchText = teamQuery.getSearchText();
            if (StringUtils.isNotBlank(searchText)) {
                queryWrapper.or().like("name", searchText);
                queryWrapper.or().like("description", searchText);
            }
            // 精确名字搜索
            String name = teamQuery.getName();
            if (StringUtils.isNotBlank(name)) {
                queryWrapper.or().like("name", name);
            }
            // 精确描述搜索
            String description = teamQuery.getDescription();
            if (StringUtils.isNotBlank(description)) {
                queryWrapper.or().like("description", description);
            }
            // 精确最大人数搜索
            Integer maxNum = teamQuery.getMaxNum();
            if (maxNum != null && maxNum > 0) {
                queryWrapper.or().eq("maxNum", maxNum);
            }
            // 精确队长ID搜索
            Long userId = teamQuery.getUserId();
            if (userId != null && userId > 0) {
                queryWrapper.or().eq("userId", userId);
            }
            // 精确状态搜索
            Integer status = teamQuery.getStatus();
            TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(status);
            if (statusEnum == null) {
                statusEnum = TeamStatusEnum.PUBLIC;
            }
            if (!userService.isAdmin(request) && !statusEnum.equals(TeamStatusEnum.PUBLIC)) {
                throw new BusinessException(ErrorCode.NO_AUTH, "无权限查看非公开队伍");
            }
            if (status != null && status > -1) {
                queryWrapper.or().eq("status", statusEnum.getValue());
            }
        }
        queryWrapper.or().gt("expireTime", new Date()).or().isNull("expireTime");
        // 所有符合条件的队伍
        List<Team> teamList = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(teamList)) {
            return new ArrayList<>();
        }

        // 信息
        List<TeamUserVO> teamUserVOS = new ArrayList<>();
        User loginUser = userService.getLoginUser(request);
        for (Team team : teamList) {
            // 设置队长信息
            Long userId = team.getUserId();  // 队长ID
            User user = userService.getById(userId);
            TeamUserVO teamUserVO = new TeamUserVO();
            BeanUtils.copyProperties(team, teamUserVO);
            if (user != null) {
                UserVO userVO = new UserVO();
                BeanUtils.copyProperties(user, userVO);
                teamUserVO.setCreateUser(userVO);
            }

            // 已加入的用户数
            Long teamId = team.getId();
            QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
            userTeamQueryWrapper.eq("teamId", teamId);
            long count = userTeamService.count(userTeamQueryWrapper);
            teamUserVO.setHasJoinNum(count);

            // 我是否加入
            Long myId = loginUser.getId();
            userTeamQueryWrapper.eq("userId", myId);
            long isJoin = userTeamService.count(userTeamQueryWrapper);
            teamUserVO.setHasJoin(isJoin > 0);
            teamUserVOS.add(teamUserVO);
        }
        return teamUserVOS;
    }


    @Override
    public boolean updateTeam(TeamUpdateRequest teamUpdateRequest, User loginUser) {
        if (teamUpdateRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍信息不合法");
        }
        Long id = teamUpdateRequest.getId();
        if (id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍ID不合法");
        }
        Team oldTeam = this.getById(id);
        if (oldTeam == null) {
            throw new BusinessException(ErrorCode.FORBIDDEN, "队伍不存在");
        }
        if (Integer.parseInt(oldTeam.getUserId().toString()) != loginUser.getId() && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "无权限操作");
        }
        TeamStatusEnum statusEnum = TeamStatusEnum.getEnumByValue(teamUpdateRequest.getStatus());
        if (statusEnum.equals(TeamStatusEnum.SECRET)) {
            if (StringUtils.isBlank(teamUpdateRequest.getPassword())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "加密房间必须要有密码");
            }
        }
        BeanUtils.copyProperties(teamUpdateRequest, oldTeam);
        return this.updateById(oldTeam);
    }

    @Override
    public Boolean joinTeam(TeamJoinRequest teamJoinRequest, User loginUser) {
        if (teamJoinRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        Long teamId = teamJoinRequest.getTeamId();
        Team team = getTeamById(teamId);
        if (team.getUserId().equals(loginUser.getId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能加入自己的队伍");
        }
        Date expireTime = team.getExpireTime();
        if (expireTime != null && expireTime.before(new Date())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍已过期");
        }
        Integer status = team.getStatus();
        TeamStatusEnum teamStatusEnum = TeamStatusEnum.getEnumByValue(status);
        if (TeamStatusEnum.PRIVATE.equals(teamStatusEnum)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍为私有，无法加入");
        }
        String password = teamJoinRequest.getPassword();
        if (TeamStatusEnum.SECRET.equals(teamStatusEnum)) {
            if (StringUtils.isNotBlank(password) && !password.equals(team.getPassword())) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误");
            }
        }
        Long id = loginUser.getId();
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", id);
        long hasJoinNum = userTeamService.count(queryWrapper);
        if (hasJoinNum > 5) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户最多加入5个队伍");
        }
        // 已加入队伍的人数
        long teamHasJoinNum = this.countTeamUser(teamId);
        if (teamHasJoinNum >= team.getMaxNum()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍人数已满");
        }
        // 不能重复加入
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userId", id).eq("teamId", teamId);
        long repeatJoinCount = userTeamService.count(queryWrapper);
        if (repeatJoinCount > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能重复加入队伍");
        }
        UserTeam userTeam = new UserTeam();
        userTeam.setUserId(id);
        userTeam.setTeamId(teamId);
        userTeam.setJoinTime(new Date());
        return userTeamService.save(userTeam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean quitTeam(TeamQuitRequest teamQuitRequest, User loginUser) {
        if (teamQuitRequest == null || loginUser == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        Long teamId = teamQuitRequest.getTeamId();
        Team team = getTeamById(teamId);
        long userId = loginUser.getId();

        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teamId", teamId).eq("userId", userId);
        long count = userTeamService.count(queryWrapper);
        if (count == 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不在队伍中");
        }

        long teamHasJoinNum = countTeamUser(teamId);
        // 队伍只有一人
        if (teamHasJoinNum == 1) {
            // 删除
            this.removeById(teamId);
            QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
            userTeamQueryWrapper.eq("teamId", teamId);
            userTeamQueryWrapper.eq("userId", userId);
            return userTeamService.remove(userTeamQueryWrapper);
        } else {
            // 队伍不止一人而且是队长
            if (team.getUserId() == userId) {
                List<UserTeam> userTeamList = userTeamMapper.getSecondJoinUser(teamId);
                if (CollectionUtils.isEmpty(userTeamList) || userTeamList.size() <= 1) {
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR);
                }
                UserTeam secondJoinUser = userTeamList.get(1);
                team.setUserId(secondJoinUser.getUserId());

                if (!this.updateById(team)) {
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新队长失败");
                }
            }
            QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
            userTeamQueryWrapper.eq("teamId", teamId).eq("userId", userId);
            return userTeamService.remove(userTeamQueryWrapper);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delTeam(long teamId, User loginUser) {
        Team team = this.getTeamById(teamId);
        Long userId = team.getUserId();
        if (!loginUser.getId().equals(userId) && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCode.NO_AUTH, "无权限操作");
        }
        // 删除关联信息
        QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();
        userTeamQueryWrapper.eq("teamId", teamId);
        boolean res = userTeamService.remove(userTeamQueryWrapper);
        if (!res) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除队伍关联信息失败");
        }
        return this.removeById(teamId);
    }

    /**
     * 统计队伍人数
     *
     * @param teamId
     * @return
     */
    private long countTeamUser(long teamId) {
        QueryWrapper<UserTeam> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("teamId", teamId);
        return userTeamService.count(queryWrapper);
    }


    /**
     * 根据队伍ID获取队伍
     *
     * @param teamId
     * @return
     */
    public Team getTeamById(Long teamId) {
        if (teamId == null || teamId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍ID不合法");
        }
        Team team = this.getById(teamId);
        if (team == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "队伍不存在");
        }
        return team;
    }
}




